package felix.things.router.mqtt.server.store.utils;

import felix.things.router.mqtt.server.common.session.SessionStore;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.codec.mqtt.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.management.ManagementFactory;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

/**
 * Created by cs on 2018
 */
public class StoreUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(StoreUtil.class);

    public static Map<String, Object> transPublishToMapBeta(SessionStore store) {
        try {
            Map<String, Object> sessionStore = new LinkedHashMap<String, Object>();
            sessionStore.put("clientId", store.getClientId());
            sessionStore.put("channelId", store.getChannelId());
            sessionStore.put("cleanSession", store.isCleanSession());
            sessionStore.put("brokerId", store.getBrokerId());
            sessionStore.put("expire", store.getExpire());
            MqttPublishMessage msg = store.getWillMessage();
            if (null != msg) {
                sessionStore.put("payload", Base64.getEncoder().encodeToString(msg.payload().array()));
                sessionStore.put("messageType", msg.fixedHeader().messageType().value());
                sessionStore.put("isDup", msg.fixedHeader().isDup());
                sessionStore.put("qosLevel", msg.fixedHeader().qosLevel().value());
                sessionStore.put("isRetain", msg.fixedHeader().isRetain());
                sessionStore.put("remainingLength", msg.fixedHeader().remainingLength());
                sessionStore.put("topicName", msg.variableHeader().topicName());
                sessionStore.put("packetId", msg.variableHeader().packetId());
                sessionStore.put("hasWillMessage", true);
            }

            return sessionStore;
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return null;
    }


    public static SessionStore mapTransToPublishMsgBeta(Map<String, Object> store) {
        SessionStore sessionStore = new SessionStore();
        Boolean hasWillMessage = Optional.ofNullable((Boolean) (store.get("hasWillMessage"))).orElse(false);
        if (hasWillMessage) {
            byte[] payloads = Base64.getDecoder().decode(store.get("payload").toString());
            ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(payloads.length);
            buf.writeBytes(payloads);
            MqttFixedHeader mqttFixedHeader = new MqttFixedHeader(
                    MqttMessageType.valueOf(Integer.parseInt(store.get("messageType").toString())),
                    Boolean.parseBoolean(store.get("isDup").toString()),
                    MqttQoS.valueOf(Integer.parseInt(store.get("qosLevel").toString())),
                    Boolean.parseBoolean(store.get("isRetain").toString()),
                    Integer.parseInt(store.get("remainingLength").toString()));

            MqttPublishVariableHeader mqttPublishVariableHeader = new MqttPublishVariableHeader(store.get("topicName").toString(),
                    Integer.parseInt(store.get("packetId").toString()));

            MqttPublishMessage mqttPublishMessage = new MqttPublishMessage(mqttFixedHeader, mqttPublishVariableHeader, buf);
            sessionStore.setWillMessage(mqttPublishMessage);
        }
        sessionStore.setChannelId(store.get("channelId").toString());
        sessionStore.setClientId(store.get("clientId").toString());
        sessionStore.setCleanSession(Boolean.parseBoolean(store.get("cleanSession").toString()));
        sessionStore.setBrokerId(store.get("brokerId").toString());
        sessionStore.setExpire(Integer.parseInt(store.get("expire").toString()));
        return sessionStore;
    }

    public static String getProcessId(String fallback) {
        String jvmName = ManagementFactory.getRuntimeMXBean().getName();
        int index = jvmName.indexOf(64);
        if (index < 1) {
            return fallback;
        } else {
            try {
                return Long.toString(Long.parseLong(jvmName.substring(0, index)));
            } catch (NumberFormatException var4) {
                return fallback;
            }
        }
    }
}
